part of '../writer.dart';

/// 在HiveWriter中，所有数据是通过id创建索引，因此比如[deleteOne]、[getOne]等方法都比同名的By函数快一个数量级(包括input写入在内)
/// 因此如果要处理足够多的数据，那么它的表现应该会远远好于普通的基于List的文件写入器
///
/// 由于这种写法对Hive的利用还不是很充分，因此效率肯定没有Hive本身快
/// 但对于很少写入，经常读取的场景来说（比如说经常使用getOne的），它的效率是还可以的
class HiveIdentityWriter<T extends IdentityOld> extends IdentityWriter<T> {
  /// 不管这个box是怎么打开的，只要想办法传入一个这样的box就可以了
  final Box<Json> box;

  /// Hive中存储的都是JsonMap格式，那么拿出来之后还需要反序列化后才能返回
  T Function(Json raw) unzip;

  HiveIdentityWriter({required this.box, required this.unzip}) {
    if (!box.isOpen) throw Bug("传入的Box没有打开");
  }

  @override
  List<T> get all => box.values.map((raw) => unzip(raw)).toList();

  @override
  bool deleteBy(Test<T> test) {
    // 遍历所有项目，如果满足条件，则删除此项
    for (int i = 0; i < box.length; i++) {
      final value = box.getAt(i) as Json;
      final object = unzip(value);
      // 如果符合条件，则在box和all中同时删除对应的内容
      if (test(object)) {
        box.deleteAt(i);
        return true;
      }
    }
    return false;
  }

  @override
  void deleteOne(String id) {
    if (!box.containsKey(id)) throw BugDev("id[$id]不存在，无法删除");
    box.delete(id);
  }

  @override
  T? findBy(Test<T> test) {
    // 遍历所有项目，找到满足条件的项
    for (final object in all) {
      if (test(object)) return object;
    }
    return null;
  }

  @override
  void input(T object) => box.put(object.id, object.toJson());

  @override
  T getOne(String id) {
    final found = findOne(id);
    if (found == null) throw BugDev("根据id[$id]找不到对象");
    return found;
  }

  @override
  T getBy(Test<T> test) {
    final obj = findBy(test);
    if (obj == null) throw Bug("没有找到对象");
    return obj;
  }

  @override
  void deletAll() => box.deleteAll(box.keys);

  @override
  T? findOne(String id) {
    final Json? raw = box.get(id);
    if (raw == null) return null;
    return unzip(raw);
  }
}
